package com.leqicheng.tenon.pay;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;

import org.apache.cordova.CallbackContext;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
import android.widget.RelativeLayout;
import android.widget.Toast;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alipay.sdk.app.PayTask;
import com.leqicheng.tenon.RuntimeActivity;
import com.leqicheng.tenon.R;
import com.leqicheng.tenon.login.PopWindow;
import com.leqicheng.tenon.login.WeixinLoginHttpRequest;
import com.leqicheng.tenon.login.weibo.AccessTokenKeeper;
import com.leqicheng.tenon.login.weibo.AuthListener;
import com.leqicheng.tenon.login.weibo.WeiboConstants;
import com.leqicheng.tenon.login.weixin.WeixinConstants;
import com.leqicheng.tenon.model.EntryInfoModel;
import com.leqicheng.tenon.pay.alipay.AlipayConstant;
import com.leqicheng.tenon.pay.alipay.ChargeAliPayHttpRequest;
import com.leqicheng.tenon.pay.alipay.PayResult;
import com.leqicheng.tenon.pay.weixin.ChargeWeixinHttpRequest;
import com.leqicheng.tenon.util.GeneralCallBack;
import com.leqicheng.tenon.util.MD5;
import com.leqicheng.tenon.util.OrientationEnum;
import com.leqicheng.tenon.util.RequestStatus;
import com.leqicheng.tenon.util.RequestTypeEnum;
import com.leqicheng.tenon.util.SignUtils;
import com.leqicheng.tenon.util.WindowStatusCode;
import com.tencent.mm.sdk.modelmsg.SendAuth;
import com.tencent.mm.sdk.modelpay.PayReq;
import com.tencent.mm.sdk.openapi.IWXAPI;
import com.tencent.mm.sdk.openapi.WXAPIFactory;

public class PopPayWindow extends PopWindow implements OnClickListener,
        GeneralCallBack {
    private CallbackContext mCallbackContext;
    private Context mContext;
    private Handler mHandler;
    private LayoutInflater mInflater;
    private LinearLayout mLayoutParent;
    private PopupWindow mPopupWindow;
    private RelativeLayout mWeiXinButton;
    private RelativeLayout mAlipayButton;
    private ImageButton mCloseWindowButton;
    private org.json.JSONArray mPayData;
    private IWXAPI mIWXAPI;
    private PayReq mPayReq;
    private PayInfoModel mPayInfoModel;
    private EntryInfoModel mEntryInfoModel;
    private static final int SDK_PAY_FLAG = 1;
    private static final int SDK_CHECK_FLAG = 2;

    public PopPayWindow(Context context, Handler handler,
            org.json.JSONArray data) {
        super();
        this.mContext = context;
        mPayData = data;
        mHandler = handler;
        this.mInflater = (LayoutInflater) this.mContext
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View layout = this.mInflater.inflate(R.layout.popwindow_pay, null);
        this.mLayoutParent = (LinearLayout) layout
                .findViewById(R.id.parent_layout);
        mWeiXinButton = (RelativeLayout) layout
                .findViewById(R.id.relative_weixin);
        mWeiXinButton.setOnClickListener(this);
        mAlipayButton = (RelativeLayout) layout
                .findViewById(R.id.relatvie_alipay);
        mAlipayButton.setOnClickListener(this);
        mCloseWindowButton = (ImageButton) layout
                .findViewById(R.id.close_window);
        mCloseWindowButton.setOnClickListener(this);
        // mLayoutParent.setOrientation(LinearLayout.VERTICAL);
        this.mPopupWindow = new PopupWindow(layout);
        this.mPopupWindow.setFocusable(true);

        // 控制popupwindow的宽度和高度自适应
        this.mLayoutParent.measure(View.MeasureSpec.UNSPECIFIED,
                View.MeasureSpec.UNSPECIFIED);
        this.mPopupWindow.setWidth(this.mLayoutParent.getMeasuredWidth() + 6);
        this.mPopupWindow.setHeight(this.mLayoutParent.getMeasuredHeight() + 6);

        // this.mPopupWindow.setBackgroundDrawable(this.mContext.getResources()
        // .getDrawable(R.drawable.boder));
        // 控制popupwindow点击屏幕其他地方消失
        // this.mPopupWindow.setOutsideTouchable(false);//
        // // 触摸popupwindow外部，popupwindow消失。这个要求你的popupwindow要有背景图片才可以成功，如上
    }

    public PopupWindow getPopupWindow() {
        return this.mPopupWindow;
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.relatvie_alipay) {
            createPayOrder();
            ChargeAliPayHttpRequest chargeAliPayHttpRequest = new ChargeAliPayHttpRequest(
                    this.mContext, this);
            chargeAliPayHttpRequest.postRequest(mPayInfoModel,
                    mEntryInfoModel.isEgretGame());
        } else if (v.getId() == R.id.relative_weixin) {
            registerWeixinPayBroadcast();
            createPayOrder();
            ChargeWeixinHttpRequest chargeWeixinHttpRequest = new ChargeWeixinHttpRequest(
                    this.mContext, this);
            chargeWeixinHttpRequest.postRequest(mPayInfoModel,
                    mEntryInfoModel.isEgretGame());
        } else if (v.getId() == R.id.close_window) {
            handlePayMessage(createDataMap(false), false);
        }
    }

    private void createPayOrder() {
        mEntryInfoModel = EntryInfoModel.getInstance();
        mPayInfoModel = PayInfoModel.getInstance();
        mPayInfoModel.setChannelId(mEntryInfoModel.getChannelId());
        mPayInfoModel.setGameId(mEntryInfoModel.getGameId());
        mPayInfoModel.setTenonUserId(mEntryInfoModel.getTenonUserId());
        String mPayDataInString = mPayData.toString();
        JSONArray payDataInJson = JSON.parseArray(mPayDataInString);
        JSONObject payDataInJsonObj = payDataInJson.getJSONObject(0);
        if (mEntryInfoModel.isEgretGame()) {
            mPayInfoModel.setEgretGameId(payDataInJsonObj.getString("gameId"));
            mPayInfoModel
                    .setEgretGoodsId(payDataInJsonObj.getString("goodsId"));
            mPayInfoModel.setEgretOrderId(payDataInJsonObj
                    .getString("egretOrderId"));
            mPayInfoModel.setPayPrice(payDataInJsonObj.getString("money"));
            mPayInfoModel.setEgretExt(payDataInJsonObj.getString("ext"));
            mPayInfoModel.setEgretTime(payDataInJsonObj.getString("time"));
            mPayInfoModel.setPayName(payDataInJsonObj.getString("goodsName"));
            mPayInfoModel.setPayDescription("游戏订单："
                    + payDataInJsonObj.getString("egretOrderId"));
        } else {
            mPayInfoModel.setPayDescription(payDataInJsonObj
                    .getString("description"));
            mPayInfoModel.setPayName(payDataInJsonObj.getString("name"));
            mPayInfoModel.setPayNotifyUrl(payDataInJsonObj
                    .getString("notify_url"));
            mPayInfoModel.setPayOrderId(payDataInJsonObj.getString("orderid"));
            mPayInfoModel.setPayPrice(payDataInJsonObj.getString("price"));
            mPayInfoModel.setPayTimeStamp(payDataInJsonObj
                    .getString("timestamp"));
        }
        mPayInfoModel.setPaySign(payDataInJsonObj.getString("sign"));

    }

    private void registerWeixinPayBroadcast() {
        IntentFilter intentFilter = new IntentFilter();

        intentFilter.addAction("weixin pay complete"); // 为BroadcastReceiver指定action，即要监听的消息名字。

        BroadcastReceiver myBroadcastReceiver = new BroadcastReceiver() {

            @Override
            public void onReceive(Context context, Intent intent) {
                mContext.unregisterReceiver(this);
                PayInfoModel model = PayInfoModel.getInstance();
                if (intent.getBooleanExtra("pay_status", false)) {
                    handlePayMessage(createDataMap(true), true);
                } else {
                    handlePayMessage(createDataMap(false), false);
                }
                model.destroyInstance();
            }
        };
        mContext.registerReceiver(myBroadcastReceiver, intentFilter); // 注册监听
    }

    private Map<String, Object> createDataMap(boolean status) {
        PayInfoModel model = PayInfoModel.getInstance();
        Map<String, Object> result = new HashMap<String, Object>();
        result.put("orderid", model.getPayOrderId());
        if (status) {
            result.put("status", "OK");
        } else {
            result.put("status", "Faild");
        }
        return result;
    }

    private void handlePayMessage(Map<String, Object> dataMap, boolean success) {
        Message msg = new Message();
        msg.what = WindowStatusCode.PAY_WINDOW_SUCCEED;
        if (success) {
            msg.arg1 = 1;
        } else {
            msg.arg1 = 0;
        }
        msg.obj = dataMap;
        mHandler.sendMessage(msg);
    }

    @Override
    public void onComplete(RequestTypeEnum requestType, int status,
            String responseBody) {
        switch (status) {
        case RequestStatus.NETWORK_ERROR:
            Toast.makeText(mContext, "网络错误", Toast.LENGTH_SHORT).show();
            break;
        case RequestStatus.OBTAIN_SUCCESS:
            switch (requestType) {
            case CHARGE_WECHAT:
                this.ProcessingChargeWechatData(responseBody);
                break;
            case CHARGE_ALIPAY:
                this.ProcessingChargeAliPayData(responseBody);
            default:
                break;
            }
            break;
        default:
            Toast.makeText(mContext, "支付失败", Toast.LENGTH_SHORT).show();
            break;
        }
        super.onComplete(requestType, status, responseBody);
    }

    private void ProcessingChargeAliPayData(String responseBody) {
        String orderPayId = "tenon"
                + JSON.parseObject(responseBody).getString("tenon_pay_id");
        mPayInfoModel.setPayId(orderPayId);
        this.payment(
                mPayInfoModel.getPayName() + mPayInfoModel.getPayDescription(),
                mPayInfoModel.getPayName() + mPayInfoModel.getPayDescription(),
                mPayInfoModel.getPayPrice(), orderPayId);
        Toast.makeText(mContext, "正在跳转支付宝支付，请等待", Toast.LENGTH_LONG).show();
    }

    private void ProcessingChargeWechatData(String responseBody) {
        String prepayId = JSON.parseObject(responseBody).getString("prepay_id");
        this.mIWXAPI = WXAPIFactory.createWXAPI(mContext, null);
        if (this.mIWXAPI.isWXAppInstalled()) {
            try {
                this.genPayReq(prepayId);
                Toast.makeText(mContext, "正在跳转微信支付，请等待", Toast.LENGTH_LONG)
                        .show();
            } catch (Exception e) {
            }
        } else {
            Toast.makeText(mContext, "您还未安装微信", Toast.LENGTH_SHORT).show();
        }
    }

    @SuppressWarnings("deprecation")
    private void genPayReq(String prepayId) {
        this.mPayReq = new PayReq();
        this.mPayReq.appId = WeixinConstants.APP_ID;
        this.mPayReq.partnerId = WeixinConstants.MCH_ID;
        this.mPayReq.prepayId = prepayId;
        this.mPayReq.packageValue = "Sign=WXPay";
        this.mPayReq.nonceStr = this.genNonceStr();
        this.mPayReq.timeStamp = String.valueOf(this.genTimeStamp());

        List<NameValuePair> signParams = new LinkedList<NameValuePair>();
        signParams.add(new BasicNameValuePair("appid", this.mPayReq.appId));
        signParams
                .add(new BasicNameValuePair("noncestr", this.mPayReq.nonceStr));
        signParams.add(new BasicNameValuePair("package",
                this.mPayReq.packageValue));
        signParams.add(new BasicNameValuePair("partnerid",
                this.mPayReq.partnerId));
        signParams
                .add(new BasicNameValuePair("prepayid", this.mPayReq.prepayId));
        signParams.add(new BasicNameValuePair("timestamp",
                this.mPayReq.timeStamp));

        this.mPayReq.sign = this.genAppSign(signParams);

        Log.e("orion", signParams.toString());

        this.mIWXAPI.registerApp(WeixinConstants.APP_ID);
        this.mIWXAPI.sendReq(this.mPayReq);

    }

    private String genNonceStr() {
        Random random = new Random();
        return MD5.getMessageDigest(String.valueOf(random.nextInt(10000))
                .getBytes());
    }

    private long genTimeStamp() {
        return System.currentTimeMillis() / 1000;
    }

    @SuppressWarnings("deprecation")
    private String genAppSign(List<NameValuePair> params) {
        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < params.size(); i++) {
            sb.append(params.get(i).getName());
            sb.append('=');
            sb.append(params.get(i).getValue());
            sb.append('&');
        }
        sb.append("key=");
        sb.append(WeixinConstants.API_KEY);

        String appSign = MD5.getMessageDigest(sb.toString().getBytes())
                .toUpperCase();
        Log.e("orion", appSign);
        return appSign;
    }

    public void payment(String subject, String body, String price, String payId) {
        if (TextUtils.isEmpty(AlipayConstant.PARTNER)
                || TextUtils.isEmpty(AlipayConstant.RSA_PRIVATE)
                || TextUtils.isEmpty(AlipayConstant.SELLER)) {
            return;
        }
        // 订单
        String orderInfo = this.getOrderInfo(subject, body, price, payId);

        // 对订单做RSA 签名
        String sign = this.sign(orderInfo);
        try {
            // 仅需对sign 做URL编码
            sign = URLEncoder.encode(sign, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        // 完整的符合支付宝参数规范的订单信息
        final String payInfo = orderInfo + "&sign=\"" + sign + "\"&"
                + this.getSignType();

        Runnable payRunnable = new Runnable() {

            @Override
            public void run() {
                // 构造PayTask 对象
                PayTask alipay = new PayTask((Activity) mContext);
                // 调用支付接口，获取支付结果
                String result = alipay.pay(payInfo);

                Message msg = new Message();
                msg.what = SDK_PAY_FLAG;
                msg.obj = result;
                payHandler.sendMessage(msg);
            }
        };

        // 必须异步调用
        Thread payThread = new Thread(payRunnable);
        payThread.start();
    }

    public String getOrderInfo(String subject, String body, String price,
            String payId) {

        // 签约合作者身份ID
        String orderInfo = "partner=" + "\"" + AlipayConstant.PARTNER + "\"";

        // 签约卖家支付宝账号
        orderInfo += "&seller_id=" + "\"" + AlipayConstant.SELLER + "\"";

        // 商户网站唯一订单号
        orderInfo += "&out_trade_no=" + "\"" + payId + "\"";

        // 商品名称
        orderInfo += "&subject=" + "\"" + subject + "\"";

        // 商品详情
        orderInfo += "&body=" + "\"" + body + "\"";

        // 商品金额
        orderInfo += "&total_fee=" + "\"" + price + "\"";

        // 服务器异步通知页面路径
        orderInfo += "&notify_url=" + "\""
                + "https://tenon-x.com/ali/notify-ali-order-result" + "\"";

        // 服务接口名称， 固定值
        orderInfo += "&service=\"mobile.securitypay.pay\"";

        // 支付类型， 固定值
        orderInfo += "&payment_type=\"1\"";

        // 参数编码， 固定值
        orderInfo += "&_input_charset=\"utf-8\"";

        // 设置未付款交易的超时时间
        // 默认30分钟，一旦超时，该笔交易就会自动被关闭。
        // 取值范围：1m～15d。
        // m-分钟，h-小时，d-天，1c-当天（无论交易何时创建，都在0点关闭）。
        // 该参数数值不接受小数点，如1.5h，可转换为90m。
        orderInfo += "&it_b_pay=\"30m\"";

        // extern_token为经过快登授权获取到的alipay_open_id,带上此参数用户将使用授权的账户进行支付
        // orderInfo += "&extern_token=" + "\"" + extern_token + "\"";

        // 支付宝处理完请求后，当前页面跳转到商户指定页面的路径，可空
        orderInfo += "&return_url=\"m.alipay.com\"";

        // 调用银行卡支付，需配置此参数，参与签名， 固定值 （需要签约《无线银行卡快捷支付》才能使用）
        // orderInfo += "&paymethod=\"expressGateway\"";

        return orderInfo;
    }

    /**
     * sign the order info. 对订单信息进行签名
     * @param content
     *            待签名订单信息
     */
    public String sign(String content) {
        return SignUtils.sign(content, AlipayConstant.RSA_PRIVATE);
    }

    /**
     * get the sign type we use. 获取签名方式
     */
    public String getSignType() {
        return "sign_type=\"RSA\"";
    }

    private final Handler payHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            boolean payStatus = false;
            switch (msg.what) {
            case SDK_PAY_FLAG: {
                PayResult payResult = new PayResult((String) msg.obj);
                // 支付宝返回此次支付结果及加签，建议对支付宝签名信息拿签约时支付宝提供的公钥做验签
                String resultInfo = payResult.getResult();
                String resultStatus = payResult.getResultStatus();
                // 判断resultStatus 为“9000”则代表支付成功，具体状态码代表含义可参考接口文档
                if (TextUtils.equals(resultStatus, "9000")) {
                    Toast.makeText(mContext, "支付成功", Toast.LENGTH_SHORT).show();
                    payStatus = true;
                } else {
                    payStatus = false;
                    // 判断resultStatus 为非“9000”则代表可能支付失败
                    // “8000”代表支付结果因为支付渠道原因或者系统原因还在等待支付结果确认，最终交易是否成功以服务端异步通知为准（小概率状态）
                    if (TextUtils.equals(resultStatus, "8000")) {
                        Toast.makeText(mContext, "支付结果确认中", Toast.LENGTH_SHORT)
                                .show();
                    } else {
                        // 其他值就可以判断为支付失败，包括用户主动取消支付，或者系统返回的错误
                        Toast.makeText(mContext, "支付失败", Toast.LENGTH_SHORT)
                                .show();
                    }
                }
                break;
            }
            case SDK_CHECK_FLAG: {
                break;
            }
            default:
                break;
            }
            handlePayMessage(createDataMap(payStatus), true);
            PayInfoModel.getInstance().destroyInstance();
        };
    };
}
